/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sales.managedbean;

import accountManagement.entity.Salesman;
import accountManagement.sessionbean.SalesmanManager;
import finance.util.exception.CreditAccountFrozenException;
import finance.util.exception.CreditLimitExceededException;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletRequest;
import mrp.util.exception.ATPFailedException;
import sales.entity.LineItem;
import sales.entity.SalesOrderEntity;
import sales.entity.SalesQuotation;
import sales.seesion.stateless.PriceManageSessionBean;
import sales.seesion.stateless.ProductManageSessionBean;
import sales.seesion.stateless.SalesOrderSessionBean;
import sales.seesion.stateless.SalesQuotationSessionBean;
import sales.util.exception.PriceUnacceptableException;
import sales.util.exception.QuotationExpiredException;
import sales.util.exception.QuotationNotFoundException;
import supplyChain.session.stateless.InventorySessionBean;

/**
 *
 * @author ReinForceII
 */
@ManagedBean
@ViewScoped
public class CreateNewPurchaseOrderManagedBean implements Serializable {

    @EJB
    SalesOrderSessionBean salesOrderSessionBean;
    @EJB
    SalesQuotationSessionBean salesQuotationSessionBean;
    @EJB
    SalesmanManager salesmanManager;
    @EJB
    ProductManageSessionBean productManageSessionBean;
    @EJB
    PriceManageSessionBean priceManageSessionBean;
    @EJB
    InventorySessionBean inventorySessionBean;
    private SalesOrderEntity salesOrder;
    private SalesQuotation salesQuotation;
    private LineItem lineItem;
    private List<LineItem> lineItemList;
    private Long quotationId;
    private Long companyId;
    private Long productId;
    private String errorMessage;
    private boolean quotationLoaded;
    private List<LineItem> quotationLineItemList;
    private final double LARGE_ORDER_AMOUNT = 500000;

    /** Creates a new instance of CreateNewPurchaseOrderManagedBean */
    public CreateNewPurchaseOrderManagedBean() throws IOException {
        lineItem = new LineItem();
        lineItemList = new ArrayList<LineItem>();
        salesOrder = new SalesOrderEntity();
        errorMessage = "";
        salesQuotation = (SalesQuotation) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("salesQuotation");
        if(salesQuotation == null){
         FacesContext.getCurrentInstance().getExternalContext().redirect("convertSalesQuotation.xhtml");
        }
        quotationLineItemList = salesQuotation.getQuotationLineItems();

    }
   
    public void addLineItem(ActionEvent event) {//TODO: 1. make sure can only add lineitem after quotation is get. 2. It's better if can have a dynamic list of products available. 3. Even better if can calculate price realtime when enter quantity.
        lineItem.setProduct(productManageSessionBean.getProductById(productId));
        boolean flag = false;

        for (LineItem item : quotationLineItemList) {

            if (item.getProduct().getId().equals(productId)) {

                flag = true;
                lineItem.setPrice(item.getPrice());
            }

        }

        if (flag) {
            lineItem.setCumAmount(priceManageSessionBean.roundTwoDecimals(lineItem.getPrice() * lineItem.getQuantity()));
            lineItemList.add(lineItem);
            lineItem = new LineItem();
            return;
        }
        setErrorMessage("Quotation does not contain this product. Please raise a new quotation if you wish to order this product.");
        return;
    }

    public void deleteLineItem(LineItem lineItem) {
        for (int i=0;i<lineItemList.size();i++){
            if (lineItemList.get(i).getQuantity()==lineItem.getQuantity()){
                lineItemList.remove(i);
            return;}
        }
//        int i=lineItemList.indexOf(lineItem);
//        lineItemList.remove(i);
    }

    public List<SelectItem> getProductList() { //This is the method that returns a dynimic list of proudcts available in the quotation

        List<SelectItem> selectItems = salesQuotationSessionBean.getProductList(getSalesQuotation());
        return selectItems;
    }

    public void createNewPurchaseOrder(ActionEvent event) throws Exception {
        double totalAmount = 0;
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        Long salesManId = (Long) request.getSession().getAttribute("userId");
        Salesman salesman = salesmanManager.getSalesmanById(salesManId);

        salesOrder.setSalesQuotation(getSalesQuotation());
        //System.out.println(salesQuotation.getId());
        //System.out.println(salesQuotation.getCompany().getName());
        salesOrder.setCustomer(getSalesQuotation().getCompany());
        if (lineItemList.isEmpty()) {
            setErrorMessage("There is no item in the ordering list.");
            return;
        }
        //set the LineItem
        salesOrder.setSalesOrderLineItems(lineItemList);
        for (LineItem item : lineItemList) {
            totalAmount = totalAmount + (item.getCumAmount());
        }
        getSalesOrder().setTotalAmount(totalAmount);

        try {

            salesOrderSessionBean.verifyPurchaseOrder(salesOrder);

        } catch (QuotationExpiredException e) {
            setErrorMessage("The quotation is expired.");
            System.out.println(getErrorMessage());
            return;
        } catch (PriceUnacceptableException e) {
            setErrorMessage("Price unacceptable, please revise.");
            System.out.println(getErrorMessage());
            return;
        } catch (QuotationNotFoundException e) {
            setErrorMessage("Quotation does not exist.");
            System.out.println(getErrorMessage());
            return;
        }

        if (totalAmount < LARGE_ORDER_AMOUNT) {
            salesOrder.setLargeOrderConfirmed(true);
        } else {
            salesOrder.setLargeOrderConfirmed(false);
        }

        salesOrder.setVerifiedBySystem(false);
        
        if (salesOrder.isLargeOrderConfirmed()) {
            try {
                salesOrder.setLargeOrderConfirmedBy(salesman);
                salesOrderSessionBean.verifySalesOrder(salesOrder);

            } catch (CreditAccountFrozenException e) {
                setErrorMessage("Credit account is frozen. Please pay outstnading bills.");
                System.out.println(getErrorMessage());
                return;
            } catch (CreditLimitExceededException e) {
                setErrorMessage("No enough credit. Please reduce amount ordered or pay cash in advance.");
                System.out.println(getErrorMessage());
                return;
            } catch (ATPFailedException e) {
                setErrorMessage("ATP failed: " + e.getMessage());
                System.out.println(getErrorMessage());
                return;
            }
            salesOrder.setVerifiedBySystem(true);
            inventorySessionBean.reserveInventory(salesOrder);
        }

        salesOrder.setDateCreated(Calendar.getInstance().getTime());
        salesOrder.setDateLastModified(Calendar.getInstance().getTime());
        
        salesOrder.setConfirmed(false);
        salesOrder.setProcessedBy(salesman);

        salesOrderSessionBean.addSalesOrder(salesOrder);
        salesQuotationSessionBean.saveChanges(salesQuotation);
        FacesContext.getCurrentInstance().getExternalContext().getFlash().put("lastURL", "viewAllPurchaseOrder.xhtml");
        FacesContext.getCurrentInstance().getExternalContext().getFlash().put("purchaseOrder", salesOrder);
        
        FacesContext.getCurrentInstance().getExternalContext().redirect("displayPurchaseOrder.xhtml");

        return;

    }

    public void calculateCumAmount(ActionEvent event) {


        boolean flag = false;

        for (LineItem item : quotationLineItemList) {

            if (item.getProduct().getId().equals(productId)) {

                flag = true;
                lineItem.setPrice(item.getPrice());
            }

        }

        if (flag) {
            lineItem.setCumAmount(priceManageSessionBean.roundTwoDecimals(lineItem.getPrice() * lineItem.getQuantity()));
            return;
        }

        return;
    }

    public SalesOrderEntity getSalesOrder() {
        return salesOrder;
    }

    public void setSalesOrder(SalesOrderEntity salesOrder) {
        this.salesOrder = salesOrder;
    }

    public LineItem getLineItem() {
        return lineItem;
    }

    public void setLineItem(LineItem lineItem) {
        this.lineItem = lineItem;
    }

    public List<LineItem> getLineItemList() {
        return lineItemList;
    }

    public void setLineItemList(List<LineItem> lineItemList) {
        this.lineItemList = lineItemList;
    }

    public Long getQuotationId() {
        return quotationId;
    }

    public void setQuotationId(Long quotationId) {
        this.quotationId = quotationId;
    }

    public Long getCompanyId() {
        return companyId;
    }

    public void setCompanyId(Long companyId) {
        this.companyId = companyId;
    }

    public Long getProductId() {
        return productId;
    }

    public void setProductId(Long productId) {
        this.productId = productId;
    }

    /**
     * @return the errorMessage
     */
    public String getErrorMessage() {
        return errorMessage;
    }

    /**
     * @param errorMessage the errorMessage to set
     */
    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    /**
     * @return the quotationLoaded
     */
    public boolean isQuotationLoaded() {
        return quotationLoaded;
    }

    /**
     * @param quotationLoaded the quotationLoaded to set
     */
    public void setQuotationLoaded(boolean quotationLoaded) {
        this.quotationLoaded = quotationLoaded;
    }

    /**
     * @return the quotationLineItemList
     */
    public List<LineItem> getQuotationLineItemList() {
        return quotationLineItemList;
    }

    /**
     * @param quotationLineItemList the quotationLineItemList to set
     */
    public void setQuotationLineItemList(List<LineItem> quotationLineItemList) {
        this.quotationLineItemList = quotationLineItemList;
    }

    public SalesQuotation getSalesQuotation() {
        return salesQuotation;
    }

    public void setSalesQuotation(SalesQuotation salesQuotation) {
        this.salesQuotation = salesQuotation;
    }
}
